Skip to content

Fix NRE in CollectDeclaredReferencesTask when ResolvedReferences is null#140

Merged
dfederm merged 1 commit intomainfrom
dfederm/fix-rt-null-resolved-references
Apr 27, 2026
Merged

Fix NRE in CollectDeclaredReferencesTask when ResolvedReferences is null#140
dfederm merged 1 commit intomainfrom
dfederm/fix-rt-null-resolved-references

Conversation

@dfederm
Copy link
Copy Markdown
Owner

@dfederm dfederm commented Apr 27, 2026

Fixes an ArgumentNullException from CollectDeclaredReferencesTask.Execute() observed on Substrate vcxproj builds with ReferenceTrimmer 3.3.12+:

error MSB4018: The "CollectDeclaredReferencesTask" task failed unexpectedly.
System.ArgumentNullException: Value cannot be null. Parameter name: source
   at System.Linq.Enumerable.SingleOrDefault[TSource](IEnumerable`1 source, Func`2 predicate)
   at ReferenceTrimmer.Tasks.CollectDeclaredReferencesTask.Execute()

Root cause

ResolvedReferences is declared ITaskItem[]? but was dereferenced unconditionally on the referenceHintPath / referenceSpec fallback path. On vcxproj projects, _ReferenceTrimmerResolvedReferences (sourced from ReferencePathWithRefAssemblies) is empty/uninitialized and MSBuild passes null to the task instead of an empty array → NRE.

Changes

  • CollectDeclaredReferencesTask.cs:
    • Guard ResolvedReferences?.SingleOrDefault(...) with the null-conditional operator.
    • Audit fix in GetPackageInfos(): short-circuit when ProjectAssetsFile is null/missing and when LockFileUtilities.GetLockFile returns null (legacy or non-SDK projects can have PackageReferences without a project.assets.json).
  • New unit tests (CollectDeclaredReferencesTaskTests.cs) drive the task directly with null inputs:
    • All collection inputs null.
    • The vcxproj repro: a Reference whose path can't be resolved locally with ResolvedReferences = null.
    • PackageReferences non-null with ProjectAssetsFile = null.
  • Tests project now references Tasks so the task can be unit-tested; small MockBuildEngine / MockTaskItem helpers added.

All other nullable collection inputs in Execute() (References, ProjectReferences, PackageReferences, IgnorePackageBuildFiles, TargetFrameworkDirectories) are already null-checked.

The task NRE'd when MSBuild passed null instead of an empty array for
`ResolvedReferences` — observed on vcxproj projects where
`ReferencePathWithRefAssemblies` is empty/uninitialized.

- Guard `ResolvedReferences` with the null-conditional operator before
  `SingleOrDefault`.
- Audit `GetPackageInfos()` for the same class of bug: a project may
  have `PackageReferences` but no `ProjectAssetsFile` (legacy / non-SDK
  projects). Short-circuit when `LockFileUtilities.GetLockFile` returns
  null instead of dereferencing it.
- Add unit tests that drive the task directly with null inputs (covers
  the vcxproj repro, all-null inputs, and PackageReferences with null
  ProjectAssetsFile). Adds a project reference from Tests to Tasks plus
  small `MockBuildEngine`/`MockTaskItem` helpers.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@dfederm dfederm merged commit dbca69c into main Apr 27, 2026
2 checks passed
@dfederm dfederm deleted the dfederm/fix-rt-null-resolved-references branch April 27, 2026 20:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant